基于WPF实现筛选下拉多选控件

您所在的位置:网站首页 wpf 考试系统 基于WPF实现筛选下拉多选控件

基于WPF实现筛选下拉多选控件

2023-04-23 05:36| 来源: 网络整理| 查看: 265

基于WPF实现筛选下拉多选控件

WPF 实现筛选下拉多选控件

框架使用.NET4 至 .NET6;Visual Studio 2022;

创建MultiSelectionSearchComboBox继承Control.

模板中创建两个ListBox

PART_Selector用来显示所有ItemPART_SearchSelector用于记录筛选到的Item

Item继承ListBoxItem并将样式模板修改为CheckBox

解决Popup中IME不跟随TextBox问题

private static extern IntPtr SetFocus(IntPtr hWnd);

当TextBox中Text发生改变时通过循环Item中的GetProperty获取特定DisplayMemberPath属性,判断是否包含输入的SearchText值,如果包含则添加PART_SearchSelector中,当SelectionChanged事件更改时将修改PART_Selector中的内容。

实现代码

1)创建MultiSelectionSearchComboBox.cs代码如下:

using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Interop; namespace WPFDevelopers.Controls {     [TemplatePart(Name = "PART_TextBox", Type = typeof(TextBox))]     [TemplatePart(Name = "PART_Popup", Type = typeof(Popup))]     [TemplatePart(Name = "PART_Selector", Type = typeof(ListBox))]     [TemplatePart(Name = "PART_SelectAll", Type = typeof(CheckBox))]     [TemplatePart(Name = "PART_SearchSelector", Type = typeof(ListBox))]     public class MultiSelectionSearchComboBox : Control     {         private const string TextBoxTemplateName = "PART_TextBox";         private const string PopupTemplateName = "PART_Popup";         private const string ListBoxTemplateName = "PART_Selector";         private const string CheckBoxTemplateName = "PART_SelectAll";         private const string ListBoxTemplateNameSearch = "PART_SearchSelector";         public static readonly RoutedEvent ClosedEvent =             EventManager.RegisterRoutedEvent("Closed",                 RoutingStrategy.Bubble,                 typeof(RoutedEventHandler),                 typeof(MultiSelectionSearchComboBox));         public static readonly DependencyProperty DisplayMemberPathProperty =            DependencyProperty.Register("DisplayMemberPath",                typeof(string),                typeof(MultiSelectionSearchComboBox),                new PropertyMetadata(string.Empty));         public static readonly DependencyProperty SelectedValuePathProperty =            DependencyProperty.Register("SelectedValuePath",                typeof(string),                typeof(MultiSelectionSearchComboBox),                new PropertyMetadata(string.Empty));         public static readonly DependencyProperty TextProperty =             DependencyProperty.Register("Text",                 typeof(string),                 typeof(MultiSelectionSearchComboBox),                 new PropertyMetadata(string.Empty));         public static readonly DependencyProperty ItemsSourceProperty =             DependencyProperty.Register("ItemsSource", typeof(IEnumerable), typeof(MultiSelectionSearchComboBox),                 new PropertyMetadata());         public static readonly DependencyProperty ItemsSourceSearchProperty =             DependencyProperty.Register("ItemsSourceSearch", typeof(IEnumerable), typeof(MultiSelectionSearchComboBox),                 new PropertyMetadata());         public static readonly DependencyProperty SelectAllContentProperty =             DependencyProperty.Register("SelectAllContent", typeof(object), typeof(MultiSelectionSearchComboBox),                 new PropertyMetadata("全选"));         public static readonly DependencyProperty IsSelectAllActiveProperty =             DependencyProperty.Register("IsSelectAllActive", typeof(bool), typeof(MultiSelectionSearchComboBox),                 new PropertyMetadata(false));         public static readonly DependencyProperty DelimiterProperty =             DependencyProperty.Register("Delimiter", typeof(string), typeof(MultiSelectionSearchComboBox),                 new PropertyMetadata(";"));         public static readonly DependencyProperty IsDropDownOpenProperty =             DependencyProperty.Register("IsDropDownOpen", typeof(bool), typeof(MultiSelectionSearchComboBox),                 new PropertyMetadata(false, OnIsDropDownOpenChanged));         public static readonly DependencyProperty MaxDropDownHeightProperty =             DependencyProperty.Register("MaxDropDownHeight", typeof(double), typeof(MultiSelectionSearchComboBox),                 new UIPropertyMetadata(SystemParameters.PrimaryScreenHeight / 3.0, OnMaxDropDownHeightChanged));         public static readonly DependencyProperty SelectedItemsProperty =             DependencyProperty.Register("SelectedItems", typeof(IList), typeof(MultiSelectionSearchComboBox),                 new FrameworkPropertyMetadata(null,                     FrameworkPropertyMetadataOptions.BindsTwoWayByDefault | FrameworkPropertyMetadataOptions.Journal,                     OnSelectedItemsChanged));         public static readonly DependencyProperty SearchWatermarkProperty =            DependencyProperty.Register("SearchWatermark",                typeof(string),                typeof(MultiSelectionSearchComboBox),                new PropertyMetadata(string.Empty));         private CheckBox _checkBox;         private ListBox _listBox;         private ListBox _listBoxSearch;         private Popup _popup;         private TextBox _textBox;         private List selectedItems;         private List selectedList;         private List selectedSearchList;         private string theLastText;         static MultiSelectionSearchComboBox()         {             DefaultStyleKeyProperty.OverrideMetadata(typeof(MultiSelectionSearchComboBox),                 new FrameworkPropertyMetadata(typeof(MultiSelectionSearchComboBox)));         }         public string Delimiter         {             get => (string)GetValue(DelimiterProperty);             set => SetValue(DelimiterProperty, value);         }         public string SelectedValuePath         {             get => (string)GetValue(SelectedValuePathProperty);             set => SetValue(SelectedValuePathProperty, value);         }         public string DisplayMemberPath         {             get => (string)GetValue(DisplayMemberPathProperty);             set => SetValue(DisplayMemberPathProperty, value);         }         public string Text         {             get => (string) GetValue(TextProperty);             set => SetValue(TextProperty, value);         }         public IEnumerable ItemsSource         {             get => (IEnumerable)GetValue(ItemsSourceProperty);             set => SetValue(ItemsSourceProperty, value);         }         public IEnumerable ItemsSourceSearch         {             get => (IEnumerable) GetValue(ItemsSourceSearchProperty);             set => SetValue(ItemsSourceSearchProperty, value);         }         public object SelectAllContent         {             get => GetValue(SelectAllContentProperty);             set => SetValue(SelectAllContentProperty, value);         }         public bool IsSelectAllActive         {             get => (bool) GetValue(IsSelectAllActiveProperty);             set => SetValue(IsSelectAllActiveProperty, value);         }         public bool IsDropDownOpen         {             get => (bool) GetValue(IsDropDownOpenProperty);             set => SetValue(IsDropDownOpenProperty, value);         }         public double MaxDropDownHeight         {             get => (double) GetValue(MaxDropDownHeightProperty);             set => SetValue(MaxDropDownHeightProperty, value);         }         public IList SelectedItems         {             get => (IList) GetValue(SelectedItemsProperty);             set => SetValue(SelectedItemsProperty, value);         }         public string SearchWatermark         {             get => (string)GetValue(SearchWatermarkProperty);             set => SetValue(SearchWatermarkProperty, value);         }         [DllImport("User32.dll")]         private static extern IntPtr SetFocus(IntPtr hWnd);         public event RoutedEventHandler Closed         {             add => AddHandler(ClosedEvent, value);             remove => RemoveHandler(ClosedEvent, value);         }         public override void OnApplyTemplate()         {             base.OnApplyTemplate();             selectedList = new List();             selectedSearchList = new List();             selectedItems = new List();             _textBox = GetTemplateChild(TextBoxTemplateName) as TextBox;             _popup = GetTemplateChild(PopupTemplateName) as Popup;             if (_popup != null)                 _popup.GotFocus += _popup_GotFocus;             _listBox = GetTemplateChild(ListBoxTemplateName) as ListBox;             _checkBox = GetTemplateChild(CheckBoxTemplateName) as CheckBox;             _listBoxSearch = GetTemplateChild(ListBoxTemplateNameSearch) as ListBox;             if (_textBox != null)             {                 _textBox.TextChanged -= _textbox_TextChanged;                 _textBox.TextChanged += _textbox_TextChanged;             }             if (_checkBox != null)             {                 _checkBox.Checked -= _checkBox_Checked;                 _checkBox.Unchecked -= _checkBox_Unchecked;                 _checkBox.Checked += _checkBox_Checked;                 _checkBox.Unchecked += _checkBox_Unchecked;             }             if (_listBox != null)             {                 _listBox.IsVisibleChanged -= _listBox_IsVisibleChanged;                 _listBox.IsVisibleChanged += _listBox_IsVisibleChanged;                 _listBox.SelectionChanged -= _listBox_SelectionChanged;                 _listBox.SelectionChanged += _listBox_SelectionChanged;             }             if (_listBoxSearch != null)             {                 _listBoxSearch.IsVisibleChanged -= _listBoxSearch_IsVisibleChanged;                 _listBoxSearch.IsVisibleChanged += _listBoxSearch_IsVisibleChanged;                 _listBoxSearch.SelectionChanged -= _listBoxSearch_SelectionChanged;                 _listBoxSearch.SelectionChanged += _listBoxSearch_SelectionChanged;             }         }         private void _listBoxSearch_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)         {             if ((bool) e.NewValue)                 UpdateIsChecked(_listBoxSearch);         }         private void _listBox_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)         {             if ((bool) e.NewValue)             {                 foreach (var item in selectedSearchList)                     if (!_listBox.SelectedItems.Contains(item))                         _listBox.SelectedItems.Add(item);                 UpdateIsChecked(_listBox);             }         }         private void UpdateIsChecked(ListBox listBox)         {             _checkBox.Checked -= _checkBox_Checked;             if (listBox.Items.Count > 0 && listBox.Items.Count == listBox.SelectedItems.Count)             {                 if (_checkBox.IsChecked != true)                     _checkBox.IsChecked = true;             }             else             {                 if (listBox.SelectedItems.Count == 0)                     _checkBox.IsChecked = false;                 else                     _checkBox.IsChecked = null;             }             _checkBox.Checked += _checkBox_Checked;         }         private void _popup_GotFocus(object sender, RoutedEventArgs e)         {             var source = (HwndSource) PresentationSource.FromVisual(_popup.Child);             if (source != null)             {                 SetFocus(source.Handle);                 _textBox.Focus();             }         }         private void _checkBox_Unchecked(object sender, RoutedEventArgs e)         {             if (_listBoxSearch.Visibility == Visibility.Visible)                 _listBoxSearch.UnselectAll();             else                 _listBox.UnselectAll();         }         private void _checkBox_Checked(object sender, RoutedEventArgs e)         {             if (_listBoxSearch.Visibility == Visibility.Visible)                 _listBoxSearch.SelectAll();             else                 _listBox.SelectAll();         }         private void Combination()         {             var seletedName = new List();             foreach (var item in _listBox.SelectedItems)             {                 var name = GetDisplayText(item);                 seletedName.Add(name);             }             foreach (var item in _listBoxSearch.SelectedItems)             {                 if (_listBox.SelectedItems.Contains(item))                     continue;                 var name = GetDisplayText(item);                 seletedName.Add(name);             }             Text = string.Join(Delimiter, seletedName.ToArray());         }         private void _listBox_SelectionChanged(object sender, SelectionChangedEventArgs e)         {             if (e.RemovedItems.Count > 0)                 foreach (var item in e.RemovedItems)                     if (_checkBox.IsChecked == true)                     {                         _checkBox.Unchecked -= _checkBox_Unchecked;                         if (_listBox.Items.Count == 1)                             _checkBox.IsChecked = false;                         else                             _checkBox.IsChecked = null;                         _checkBox.Unchecked += _checkBox_Unchecked;                     }             if (e.AddedItems.Count > 0)                 SelectionChecked(_listBox);             Combination();             SelectedItems = _listBox.SelectedItems;         }         private void _listBoxSearch_SelectionChanged(object sender, SelectionChangedEventArgs e)         {             if (!_listBoxSearch.IsVisible) return;             if (e.RemovedItems.Count > 0)             {                 foreach (var item in e.RemovedItems)                     if (selectedSearchList.Contains(item))                         selectedSearchList.Remove(item);                 Combination();                 SelectionChecked(_listBoxSearch);             }             if (e.AddedItems.Count > 0)             {                 foreach (var item in e.AddedItems)                     if (!selectedSearchList.Contains(item))                         selectedSearchList.Add(item);                 Combination();                 SelectionChecked(_listBoxSearch);             }         }         private void SelectionChecked(ListBox listbox)         {             if (listbox.SelectedItems.Count > 0                 &&                 listbox.Items.Count == listbox.SelectedItems.Count)             {                 _checkBox.Checked -= _checkBox_Checked;                 _checkBox.IsChecked = true;                 _checkBox.Checked += _checkBox_Checked;             }             else             {                 _checkBox.Checked -= _checkBox_Checked;                 if (listbox.SelectedItems.Count > 0                     &&                      listbox.Items.Count == listbox.SelectedItems.Count)                 {                     if (_checkBox.IsChecked != true)                         _checkBox.IsChecked = true;                 }                 else                 {                     if (listbox.SelectedItems.Count == 0)                         _checkBox.IsChecked = false;                     else                         _checkBox.IsChecked = null;                 }                 _checkBox.Checked += _checkBox_Checked;             }         }         private string GetDisplayText(object dataItem, string path = null)         {             if (dataItem == null) return string.Empty;             return GetPropertyValue(dataItem);         }         private void _textbox_TextChanged(object sender, TextChangedEventArgs e)         {             if (string.IsNullOrWhiteSpace(theLastText)) theLastText = _textBox.Text;             SearchText(_textBox.Text);         }         private void SearchText(string _text)         {             var text = _text;             if (string.IsNullOrWhiteSpace(text))             {                 if (_listBoxSearch.Visibility != Visibility.Collapsed)                     _listBoxSearch.Visibility = Visibility.Collapsed;                 if (_listBox.Visibility != Visibility.Visible)                     _listBox.Visibility = Visibility.Visible;             }             else             {                 if(_listBoxSearch.Visibility != Visibility.Visible)                     _listBoxSearch.Visibility = Visibility.Visible;                 if(_listBox.Visibility != Visibility.Collapsed)                     _listBox.Visibility = Visibility.Collapsed;                 var listSearch = new List();                 foreach (var item in _listBox.Items)                 {                     var str = GetPropertyValue(item);                     if (!string.IsNullOrWhiteSpace(str))                         if (str.Contains(text.ToUpperInvariant()))                             listSearch.Add(item);                 }                 foreach (var item in selectedList)                     if (!listSearch.Contains(item))                         listSearch.Add(item);                 var lastItem = ItemsSourceSearch;                 ItemsSourceSearch = listSearch;                 SelectionChecked(_listBoxSearch);                 selectedItems.Clear();                 foreach (var item in _listBoxSearch.Items)                     if (_listBox.SelectedItems.Contains(item))                         if (!_listBoxSearch.SelectedItems.Contains(item))                             _listBoxSearch.SelectedItems.Add(item);             }         }         private string GetPropertyValue(object item)         {             var result = string.Empty;             var nameParts = DisplayMemberPath.Split('.');             if (nameParts.Length == 1)             {                 var property = item.GetType().GetProperty(DisplayMemberPath);                 if (property != null)                     return (property.GetValue(item, null) ?? string.Empty).ToString();             }             return result.ToUpperInvariant();         }         private static void OnIsDropDownOpenChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)         {             var multiSelectionSearchComboBox = o as MultiSelectionSearchComboBox;             if (multiSelectionSearchComboBox != null)                 multiSelectionSearchComboBox.OnIsOpenChanged((bool) e.OldValue, (bool) e.NewValue);         }         protected virtual void OnIsOpenChanged(bool oldValue, bool newValue)         {             if (!newValue)                 RaiseRoutedEvent(ClosedEvent);         }         private void RaiseRoutedEvent(RoutedEvent routedEvent)         {             var args = new RoutedEventArgs(routedEvent, this);             RaiseEvent(args);         }         private static void OnMaxDropDownHeightChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)         {             var comboBox = o as MultiSelectionSearchComboBox;             if (comboBox != null)                 comboBox.OnMaxDropDownHeightChanged((double) e.OldValue, (double) e.NewValue);         }         protected virtual void OnMaxDropDownHeightChanged(double oldValue, double newValue)         {         }         private static void OnSelectedItemsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)         {             var mltiSelectionSearchComboBox = d as MultiSelectionSearchComboBox;             if (e.NewValue != null)             {                 var collection = e.NewValue as IList;                 if (collection.Count                          mltiSelectionSearchComboBox.GetPropertyValue(h).ToUpperInvariant()                             .Equals(name));                     if (model != null && !mltiSelectionSearchComboBox._listBox.SelectedItems.Contains(item))                         mltiSelectionSearchComboBox._listBox.SelectedItems.Add(model);                     if (e.OldValue != null && mltiSelectionSearchComboBox._listBox != null)                         mltiSelectionSearchComboBox._listBox.SelectionChanged +=                             mltiSelectionSearchComboBox._listBox_SelectionChanged;                     mltiSelectionSearchComboBox.Combination();                 }             }         }     } }

2)创建MultiSelectionListBox.xaml代码如下:

using System.Windows; using System.Windows.Controls; namespace WPFDevelopers.Controls {     public class MultiSelectionListBox:ListBox     {         protected override bool IsItemItsOwnContainerOverride(object item)         {             return item is MultiSelectComboBoxItem;         }         protected override DependencyObject GetContainerForItemOverride()         {             return new MultiSelectComboBoxItem();         }     } }

3)创建MultiSelectionSearchComboBox.xaml代码如下:

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     

4)创建MultiSelectSearchComboBoxExample.xaml代码如下:

                                                                                                                                                                                                                                                                                                                       

5)创建MultiSelectSearchComboBoxExample.xaml.cs代码如下:

using System.Windows; using System.Windows.Controls; namespace WPFDevelopers.Samples.ExampleViews {     ///      /// MultiSelectComboBoxExample.xaml 的交互逻辑     ///      public partial class MultiSelectSearchComboBoxExample : UserControl     {         public MultiSelectSearchComboBoxExample()         {             InitializeComponent();         }         private void Button_Click(object sender, System.Windows.RoutedEventArgs e)         {             WPFDevelopers.Controls.MessageBox.Show($"{MyMultiSelectionSearchComboBox2.Text} \r\n总共选中:{MyMultiSelectionSearchComboBox2.SelectedItems.Count} 条","选中内容",MessageBoxButton.OK,MessageBoxImage.Information);               }     } }

效果图

以上就是基于WPF实现筛选下拉多选控件的详细内容,更多关于WPF筛选下拉多选控件的资料请关注编程宝库其它相关文章!

下一节:C#预处理器指令的用法C# 教程

 1. 预处理器指令的概念预处理器指令是指编译器在实际编译开始之前对信息进行预处理。通常用于简化源程序在不同的执行环境中的更改和编译。例如可以替换文本中的标记,将其他内容插入源文件,或者通过移除几个部分的文 ...



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3